/*
 * MasterMain.cpp
 *
 *  Created on: Feb 19, 2012
 *      Author: hduser
 */

#include<iostream>
#include<exception>
#include<string>
#include <stdio.h>
#include<cctype>
#include<iomanip>
#include<sstream>

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>


#include <errno.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <sys/signal.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <iostream>
#include<fstream>
#include<string>
#include<exception>
#include<vector>
#include "MasterServer.h"
#include "CDNBitStreamExtract.h"

#define FILENAME_SIZE 256
#define QLEN		128

#define BUFFER_SIZE	4096 //data unit size the edge server is supposed to receive


const int CMD_LENGTH = 10;
const char* CMD_NEWDATA = "cmd_nwdata";
const char* ACK_NEWDATA = "ack_nwdata";
const char* CMD_REDY = "cmd__ready";


int		passiveTCP(const char *service, int qlen);
void	* ProcessFileRequest(int fd);
//Function to split the "," separated values to string array
void split(string& s, char c,vector<string>& v)
{
    string::size_type i = 0;
    string::size_type j = s.find(c);
    while (j != string::npos)
    {
        v.push_back(s.substr(i, j-i));
        i = ++j;
        j = s.find(c, j);
        if (j == string::npos)
            v.push_back(s.substr(i, s.length( )));
    }
}



using namespace std;

int main(int argc, char **argv)
{
	pthread_t th_ProcessReq;
	pthread_attr_t ta_ProcessReq;

	MasterServer* server = new MasterServer();
	//server->ProcessVideoFile(57,"/home/nikhil/zearth_qcif_cif_4cif.svc");

	//server->ProcessFile(1, "/CMPE294_ProjectReport.pdf");
	//CDNBitStreamExtract *cdnBitExtract=new CDNBitStreamExtract();
	//cdnBitExtract->SelectLayerIdstoExtract("/home/nikhil/zearth_qcif_cif_4cif.svc");
	//cdnBitExtract->simpleRun("/home/nikhil/zearth_qcif_cif_4cif.svc");


	struct	sockaddr_in fsin;	/* the from address of a client	*/
	char	*service = "7878";  /* default port number	*/
	int	msock, ssock,num_bytes;		/* master & slave sockets	*/
	unsigned int	alen;		/* from-address length		*/

	switch (argc)
		 {
		case	1:
			cout<<"trig1"<<endl;
			break;
		case	2:
			service = argv[1];
			break;
		default:
			cerr<<"usage: TCPMASterServer [port]\n"<<endl;
			exit(1);
		}


	(void) pthread_attr_init(&ta_ProcessReq);
		(void) pthread_attr_setdetachstate(&ta_ProcessReq, PTHREAD_CREATE_DETACHED);

	msock = passiveTCP(service, QLEN);


	while (1)
		{

			alen = sizeof(fsin);
			ssock = accept(msock, (struct sockaddr *)&fsin, &alen);
			if (ssock < 0)
			{
				if (errno == EINTR)
					continue;
				cerr<<"accept: "<< strerror(errno)<<endl;
			}


			char 	*cmd;
			cmd=(char *)malloc(CMD_LENGTH);
			//receive command from the client (Push new data)
			num_bytes = recv(ssock, cmd, 10,0);

			if(num_bytes < 0)
			{
				cerr<<"Error reading from client"<<cmd<<num_bytes;
				return -1;
			}

			cerr<<"success reading from the client :"<<cmd<<"and bytes received is :"<<num_bytes<<endl;
			//printf("Success reading from client %s %d\n", cmd, num_bytes);

			cmd[num_bytes] = '\0';

			//cerr<<"Entered this area222"<<endl;

			//const char *strAcceptFile="acceptfile";

			if(!strcmp(cmd,CMD_NEWDATA))
			{
				//ProcessFileRequest(ssock);
				if(pthread_create(&th_ProcessReq,&ta_ProcessReq,(void * (*)(void *))ProcessFileRequest,(void*) ssock)<0)
					cerr<<"pthread create for ProcessFileRequest: "<<endl;
					//errexit("pthread create for ProcessFileRequest: %s",strerror(errno));

			}
			else
			{
				cerr<<"Request from client Unrecognized"<<endl;
			}


		}
}


void * ProcessFileRequest(int fd)
{
	int	num_read_bytes=-1,num_bytes_fname=-1, status;	// number of bytes received and integer from client
	char 	buf[BUFFER_SIZE];// buffer for storing bytes from file we have to decide dynamic size of this buffer
	char * fname;
	char *vendorID;
	MasterServer* server = new MasterServer();


	//SEND ACK_NEWDATA to client
	(void) send(fd,ACK_NEWDATA,10,0);


	//Block to receive the file name and vendor ID comma separated from the client
	fname = (char *)malloc(FILENAME_SIZE);

	size_t fileSize=FILENAME_SIZE;
	size_t returnBuffersize=0;
	size_t temppos= returnBuffersize;
	char * ActualBuffer=new char [FILENAME_SIZE];

	while((num_bytes_fname = recv(fd, fname, FILENAME_SIZE,0)) > 0)
	{
		temppos= returnBuffersize;
		returnBuffersize+=num_bytes_fname;

		ActualBuffer =(char *)realloc(ActualBuffer,returnBuffersize);
		memcpy(ActualBuffer+temppos,fname,num_bytes_fname);
		cout<<"num_bytes_fname = "<<num_bytes_fname<<endl;

		if (num_bytes_fname < FILENAME_SIZE)
		break;
	}

	if(num_bytes_fname < 0)
	{
			printf("Error reading from client %s %d\n", fname, num_bytes_fname);
			exit(1);
	}
	fname[returnBuffersize] = '\0';

	if(errno==0)
	{
		cerr<<"received fname path from teh client is :"<<fname<<endl;
		cerr<<"Ready to receive vendor ID from client"<<endl;
		// SEND_READY
			(void) send(fd,CMD_REDY,10,0);

	}
	else
	{
			cerr<<"Terminating application as File Name info is not received completely"<<endl;
			exit(1);
	}

	vector<string> vecPathVEndorID;
	string sPathVEndorID(fname);
	split(sPathVEndorID,',',vecPathVEndorID);

	if(vecPathVEndorID.size()==2)
	{
		cerr<<"File path is :"<<vecPathVEndorID[0]<<"And vendor id is :"<<vecPathVEndorID[1];


	}

	int intVendorID;
	intVendorID=atoi(vecPathVEndorID[1].c_str());
	cerr<<"Integer vendor id is :"<<intVendorID<<endl;


	/*
	//Block to receive Vendor ID from the client

		vendorID= (char *) malloc(sizeof(int));
		recv(fd,vendorID,sizeof(int)*8,0);
		cerr<<"Vendor id received from the client is :"<<vendorID<<endl;
		int intVendorID;
		if(vendorID!=NULL)
		 intVendorID=atoi(vendorID);
		else
		{
			cerr<<"unable to receive vendorid from the client"<<endl;
			exit(1);
		}

		cerr<<"Integer vendor id is :"<<intVendorID<<endl;
		*/


		cerr<<"Successfully received vendor ID and File Name can now invoke ProcessVideoFile"<<endl;

		//vector used to store directory hierarchy with last index as file name
			vector<string> vecFileHierarchy;
			int lenVecHierarchy;
			string strFileName;

			split(vecPathVEndorID[0],'/',vecFileHierarchy);
			if (vecFileHierarchy.size() > 0)
			{

			 lenVecHierarchy=vecFileHierarchy.size();
			strFileName=vecFileHierarchy[lenVecHierarchy-1];
			}
			else
			{
				strFileName=vecPathVEndorID[0];
			}



			//Block to check if the file is a video file(.264/.svc ) or Non-video file
			vector<string> vecFileExtension;
			//split the file name based on period so that the file extension is in the array positioned at
			//location vecFileExtension[1]
			split(strFileName,'.',vecFileExtension);

			if(vecFileExtension.size()>0)
			{

				if(strcmp(vecFileExtension[1].c_str(),"264")==0 || strcmp(vecFileExtension[1].c_str(),"svc")==0)
				{

					cerr<<"File is a video file so invoke ProcessVideoFile"<<endl;
					server->ProcessVideoFile(intVendorID,(char *)vecPathVEndorID[0].c_str());
				}
				else
				{
					cerr<<"File is a video file so invoke ProcessVideoFile"<<endl;
					server->ProcessFile(intVendorID,(char *)vecPathVEndorID[0].c_str());

				}
			}
			else
			{

				cerr<<"Unable to understand File Extension so terminating application"<<endl;
				exit(1);
			}



		//MasterServer* server = new MasterServer();
		//server->ProcessVideoFile(intVendorID,fname);
		(void) close(fd);

}


